/*  
 * Copyright (C) 2011 Marta Spodymek
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *  
 */
package org.prometheuscode.web.feedback.service;

import java.util.List;
import java.util.Map;
import java.util.Set;

import org.prometheuscode.web.feedback.ApplicationConfig;
import org.prometheuscode.web.feedback.binding.IBindingHolder;
import org.prometheuscode.web.feedback.binding.InputBinder;
import org.prometheuscode.web.feedback.dao.IFeedDao;
import org.prometheuscode.web.feedback.domain.FeedInput;
import org.prometheuscode.web.feedback.domain.IFeed;
import org.prometheuscode.web.feedback.domain.IFeedInput;
import org.prometheuscode.web.feedback.file.FileInfo;
import org.prometheuscode.web.feedback.file.FileStrategyInfo;
import org.prometheuscode.web.feedback.file.IFileHandler;
import org.prometheuscode.web.feedback.filestrategy.FileStrategyConfigurer;

import org.springframework.beans.factory.annotation.Autowired;

/**
 * Implements {@link IFeedService}.
 * 
 * @author marta
 * 
 */
public class FeedService implements IFeedService {

    private IFeedDao feedDao;

    private ApplicationConfig config;

    private IFileHandler fileHandler;

    private FileStrategyConfigurer fileStrategyConfigurer;

    public FeedService() {
    }

    /*
     * Setters and getters
     */

    public IFileHandler getFileHanlder() {
	return this.fileHandler;
    }

    @Autowired
    public void setFileHandler(IFileHandler fileHanlder) {
	this.fileHandler = fileHanlder;
    }

    public FileStrategyConfigurer getFileStrategyConfigurer() {
	return this.fileStrategyConfigurer;
    }

    @Autowired
    public void setFileStrategyConfigurer(
	    FileStrategyConfigurer fileStrategyConfigurer) {
	this.fileStrategyConfigurer = fileStrategyConfigurer;
    }

    @Autowired
    public void setFeedDao(IFeedDao feedDao) {
	this.feedDao = feedDao;
    }

    public IFeedDao getFeedDao() {
	return this.feedDao;
    }

    @Autowired
    public void setConfig(ApplicationConfig config) {
	this.config = config;
    }

    public ApplicationConfig getConfig() {
	return this.config;
    }

    /*
     * Interface Methods
     */

    @Override
    public List<IFeed> getUserFeeds(String userLogin) {

	return this.feedDao.getAllUserFeeds(userLogin);
    }

    @Override
    public IFeed getFeed(String feedId) {
	IFeed feed = this.feedDao.getFeed(feedId);

	return feed;
    }

    @Override
    public IFeed getFeedWithData(String feedId) {
	IFeed feed = this.feedDao.getFeedWithInputs(feedId);

	return feed;
    }

    @Override
    public void updateFormInputs(IBindingHolder input, IFeed feedToUpdate) {

	List<FileInfo> files = input.getFiles();
	Map<String, String> inputsParams = input.getInputs();
	/*
	 * if there are no files, we do not care else apply configureted
	 * strategy.
	 */
	if (!(files.isEmpty())) {
	    FileStrategyInfo info = this.fileStrategyConfigurer.configure(
		    feedToUpdate, files, inputsParams);
	    this.fileHandler.handle(info);
	}
	IFeed feedConverted = this.convertInput(feedToUpdate, inputsParams);

	this.feedDao.saveFeedInputs(feedConverted);
    }

    /*
     * Converts posted data into ready-to-save representation.
     */
    private IFeed convertInput(IFeed feed, Map<String, String> postData) {
	Map<String, IFeedInput> inputs = feed.getUserFormInput();

	Set<String> inputsKeys = inputs.keySet();
	Set<String> postedKeys = postData.keySet();

	for (String key : inputsKeys) {

	    /*
	     * Deselected multiselect box are not sent by the browsers in submit
	     * if they are already in data source just clean them.
	     */
	    if (!postData.containsKey(key)) {
		postData.put(key, "");
	    }
	}

	/* update or add new elements */
	for (String postedInputName : postedKeys) {

	    /*
	     * if input is empty and there is no data in data source already
	     * then skip it.
	     */
	    String postedInput = postData.get(postedInputName);
	    if (postedInput.equals("")
		    && !(inputs.containsKey(postedInputName))) {
		continue;
	    }

	    /*
	     * If this is value should not be updated, then skip it also. It is
	     * for a text input edit if file was already uploaded, and user want
	     * to keep it. TODO try to think about it.
	     */
	    if (postedInput.equals(InputBinder.NOT_UPDATEABLE_STATUS)) {
		continue;
	    }

	    /*
	     * if input does not exist in data source(for ex. database), then
	     * create one
	     */
	    IFeedInput in = inputs.get(postedInputName);
	    if (in == null) {
		/*
		 * This can be put in factory
		 */
		in = new FeedInput();
		in.setFeed(feed);
		in.setName(postedInputName);
		inputs.put(postedInputName, in);
	    }

	    in.setAnswer(postedInput);

	}

	return feed;
    }
}
